import React, { Component } from 'react';
import { Chart, Tooltip, Geom, Coord } from 'bizcharts';
import { DataView } from '@antv/data-set';
import { Row, Col } from 'antd';
import classNames from 'classnames';
import ReactFitText from 'react-fittext';
import Debounce from 'lodash-decorators/debounce';
import Bind from 'lodash-decorators/bind';
import ResizeObserver from 'resize-observer-polyfill';
import styles from './index.less';

/* eslint react/no-danger:0 */
class Pie extends Component {
  state = {
    height: 0,
    legendData: [],
    legendBlock: false,
  };

  componentDidMount() {
    window.addEventListener(
      'resize',
      () => {
        this.requestRef = requestAnimationFrame(() => this.resize());
      },
      { passive: true }
    );
    this.resizeObserver();
  }

  componentDidUpdate(preProps) {
    const { data } = this.props;
    if (data !== preProps.data) {
      // because of charts data create when rendered
      // so there is a trick for get rendered time
      this.getLegendData();
    }
  }

  componentWillUnmount() {
    window.cancelAnimationFrame(this.requestRef);
    window.removeEventListener('resize', this.resize);
    this.resize.cancel();
  }

  getG2Instance = chart => {
    this.chart = chart;
    requestAnimationFrame(() => {
      this.getLegendData();
      this.resize();
    });
  };

  // for custom lengend view
  getLegendData = () => {
    if (!this.chart) return;
    const geom = this.chart.getAllGeoms()[0]; // 获取所有的图形
    if (!geom) return;
    const items = geom.get('dataArray') || []; // 获取图形对应的

    const legendData = items.map(item => {
      /* eslint no-underscore-dangle:0 */
      const origin = item[0]._origin;
      origin.color = item[0].color;
      origin.checked = true;
      return origin;
    });

    this.setState({ legendData });
  };

  handleRoot = n => {
    this.root = n;
  };

  handleLegendClick = (item, i) => {
    const newItem = item;
    newItem.checked = !newItem.checked;

    const { legendData } = this.state;
    legendData[i] = newItem;

    const filteredLegendData = legendData.filter(l => l.checked).map(l => l.x);

    if (this.chart) {
      this.chart.filter('x', val => filteredLegendData.indexOf(val) > -1);
    }

    this.setState({ legendData });
  };

  resizeObserver() {
    const ro = new ResizeObserver(entries => {
      const { height } = entries[0].contentRect;
      this.setState(preState => {
        if (preState.height !== height) {
          return { height };
        }
        return null;
      });
    });
    if (this.chartDom) {
      ro.observe(this.chartDom);
    }
  }

  // for window resize auto responsive legend
  @Bind()
  @Debounce(300)
  resize() {
    const { hasLegend } = this.props;
    const { legendBlock } = this.state;
    if (!hasLegend || !this.root) {
      window.removeEventListener('resize', this.resize);
      return;
    }
    if (this.root.parentNode.clientWidth <= 380) {
      if (!legendBlock) {
        this.setState({ legendBlock: true });
      }
    } else if (legendBlock) {
      this.setState({ legendBlock: false });
    }
  }

  render() {
    const {
      valueFormat,
      subTitle,
      total,
      hasLegend = false,
      className,
      style,
      height = 300,
      percent,
      inner = 0.75,
      animate = true,
      colors,
      lineWidth = 1,
    } = this.props;

    const { legendData, legendBlock } = this.state;
    const pieClassName = classNames(styles.pie, className, {
      [styles.hasLegend]: !!hasLegend,
      [styles.legendBlock]: legendBlock,
    });

    const {
      data: propsData,
      selected: propsSelected = true,
      tooltip: propsTooltip = true,
    } = this.props;

    let data = propsData || [];
    let selected = propsSelected || true;
    let tooltip = propsTooltip || true;

    const scale = {
      x: {
        type: 'cat',
        range: [0, 1],
      },
      y: {
        min: 0,
      },
    };

    if (percent || percent === 0) {
      selected = false;
      tooltip = false;

      data = [
        {
          x: '占比',
          y: parseFloat(percent),
        },
        {
          x: '反比',
          y: 100 - parseFloat(percent),
        },
      ];
    }

    const tooltipFormat = [
      'x*percent',
      (x, p) => ({
        name: x,
        value: `${(p * 100).toFixed(2)}%`,
      }),
    ];

    const padding = [12, 0, 12, 0];

    const dv = new DataView();
    dv.source(data).transform({
      type: 'percent',
      field: 'y',
      dimension: 'x',
      as: 'percent',
    });

    return (
      <div ref={this.handleRoot} className={pieClassName} style={style}>
        <Row type="flex" align="middle" justify="space-around">
          <Col span={12}>
            <div
              ref={ref => {
                this.chartDom = ref;
              }}
            >
              <ReactFitText maxFontSize={25}>
                <div className={styles.chart}>
                  <Chart
                    scale={scale}
                    height={height}
                    data={dv}
                    padding={padding}
                    animate={animate}
                    onGetG2Instance={this.getG2Instance}
                  >
                    {!!tooltip && <Tooltip showTitle={false} />}
                    <Coord type="theta" innerRadius={inner} />
                    <Geom
                      style={{ lineWidth, stroke: 'white' }}
                      tooltip={tooltip && tooltipFormat}
                      type="intervalStack"
                      position="percent"
                      color={colors}
                      selected={selected}
                    />
                  </Chart>
                  {(subTitle || total) && (
                    <div className={styles.total}>
                      {subTitle && <h4 className="pie-sub-title">{subTitle}</h4>}
                      {/* eslint-disable-next-line */}
                      {total && (
                        <div className="pie-stat">
                          {typeof total === 'function' ? total() : total}
                        </div>
                      )}
                    </div>
                  )}
                </div>
              </ReactFitText>
            </div>
          </Col>
          <Col span={12}>
            {hasLegend && (
              <ul className={styles.legend}>
                {legendData.map((item, i) => (
                  <li key={item.x} onClick={() => this.handleLegendClick(item, i)}>
                    <span
                      className={styles.dot}
                      style={{
                        backgroundColor: !item.checked ? 'darkgray' : item.color,
                      }}
                    />
                    <span className={styles.percent}>{item.x}</span>
                    <span style={{ marginLeft: 8 }}>
                      {valueFormat ? valueFormat(item.y) : item.y}
                    </span>
                  </li>
                ))}
              </ul>
            )}
          </Col>
        </Row>
      </div>
    );
  }
}

export default Pie;
